// 棋子类
class chess {
  constructor(
    dom,
    blank,
    colorType,
    canFalling,
    value, // 价值
    x,
    y,
    east,
    south,
    west,
    north,
    eastSouth,
    eastNorth,
    westSouth,
    westNorth
  ) {
    this.dom = dom; // 棋子对应的dom对象
    this.blank = blank; // 是否空子 还没落子
    this.colorType = colorType; // 棋子颜色 1 为黑色 2 为白色 0 为无子
    this.canFalling = canFalling; // 棋子颜色 1 为黑色 2 为白色 0 为无子
    this.value = value; // 棋子颜色 1 为黑色 2 为白色 0 为无子
    this.x = x; // 棋子在棋盘中横向方向的位置 x 轴 整数
    this.y = y; // 棋子在棋盘中纵向方向的位置 y 轴 整数
    this.east = east; // 东边方向上的棋子 类型为 chess类 下面参数类推
    this.south = south;
    this.west = west;
    this.north = north;
    this.eastSouth = eastSouth;
    this.eastNorth = eastNorth;
    this.westSouth = westSouth;
    this.westNorth = westNorth;
  }

  get colorType() {
    return this._colorType;
  }

  set colorType(value) {
    this._colorType = value;
    if (typeof this.dom === "object") {
      if (value === 2) {
        this.dom.childNodes[0].classList.add("change");
      }
      if (value === 1) {
        this.dom.childNodes[0].classList.remove("change");
      }
    }
  }
}

// 棋盘类
class chessBoard {
  constructor(dimension, width, container, currentColorType, aiColor) {
    this.dimension = dimension; // 棋盘高宽
    this.width = width; // 棋格宽度
    this.container = container; // 棋盘父容器
    this.currentColorType = currentColorType; // 当前将落子棋子颜色 1黑子 2白子
    this.aiColor = aiColor; // 机器人执子颜色
  }

  _blackChess = 2; // 黑棋数量
  _whiteChess = 2; // 白棋数量
  _tipDom = null; // 棋盘父容器
  _diffs = []; // 受影响的棋子
  _dots = []; // 可以落子的节点
  _infoDom = null; // 棋盘父容器
  _timer = null; // 棋盘父容器
  _board; // 棋盘model
  _storeChess; // 当前要处理的棋子
  _falled = []; // 已经落子的节点集合

  _maxValue = 100; // 定子 金角
  _secondValue = 45 // 
  _thirdValue = 10
  _fourValue = 5
  _fiveValue = 3
  _sixValue = 2
  _sevenValue = 1
  _eightValue = -5
  _nineValue = -45

  _minValue = -45;

  _goldCorner = []; // 金角
  // _silverSide = []; // 银边
  // _greenTerf = []; // 绿草皮

  _direct = [
    // 八方向量
    [1, 0, "east"],
    [0, 1, "south"],
    [-1, 0, "west"],
    [0, -1, "north"],
    [1, 1, "eastSouth"],
    [1, -1, "eastNorth"],
    [-1, 1, "westSouth"],
    [-1, -1, "westNorth"],
  ];
  _cornerDirect1 = [
    ["east", "south"],
    ["west", "south"],
    ["east", "north"],
    ["west", "north"],
  ];
  _cornerDirect2 = [
    ["eastSouth", "westNorth"],
    ["westSouth", "easthNorth"],
    ["eastNorth", "westSouth"],
    ["westNorth", "eastSouth"],
  ];
  _goldCornerDirect = [
    ["west", "north", "westNorth"],
    ["east", "north", "eastNorth"],
    ["east", "south", "eastSouth"],
    ["west", "south", "westSouth"],
  ];
  _storeGoldCorner = null; // 存储当前处理的金角
  makeDirect(inChess) {
    // 生成八向链表
    const dimension = this.dimension;
    this._direct.map((d) => {
      let [x, y] = [inChess.x, inChess.y];
      let dx = d[0];
      let dy = d[1];
      while (true) {
        x += dx;
        y += dy;
        if (x < 0 || x >= dimension || y < 0 || y >= dimension) {
          inChess = this._storeChess;
          break;
        }
        inChess[d[2]] = this._board[y][x];
        // if (!inChess[d[2]]) {
        // }
        inChess = inChess[d[2]];
        // console.log(`x:${x} y:${y}`)
      }
    });
    return this;
  }

  getBoard() {
    // console.log('this._board', this._board)
    return this._board;
  }

  initBoard() {
    this.container.innerHTML = "";
    const dimension = this.dimension;
    const lenDimension = dimension - 1
    const width = Math.floor(this.width);
    const middle = dimension >> 1;
    const boardArr = new Array(dimension);
    // let valueStrs = "";
    for (let i = 0; i < dimension; i++) {
      let valueStr = "";
      boardArr[i] = new Array(dimension);
      for (let j = 0; j < dimension; j++) {
        let dom = document.createElement("div");
        dom.classList.add("chess-wrap");
        dom.style.width = width + "px";
        dom.style.height = width + "px";
        let childDom;
        // const middle = dimension >> 1;

        const resMiddle = i >= middle || j >= middle ? middle - 1 : middle;

        let newChess = new chess(
          dom,
          true,
          0,
          false,
          Math.abs(resMiddle - Math.max(i, j)) === 0
            ? 1
            : Math.abs(resMiddle - Math.max(i, j)),
          j,
          i,
          null,
          null,
          null,
          null,
          null,
          null,
          null,
          null
        );
        // 计算价值

        // if ((i === 0 && j === 0) || (i === 1 && j === 0) || (i === 0 && j === 1)) {
        //   childDom = this.makeChessDom();
        //   dom.appendChild(childDom);
        //   newChess.colorType = 2; // 初始化白子
        //   newChess.blank = false;
        // } else 
        if (
          (i === middle - 1 && j === middle - 1) ||
          (i === middle && j === middle)
        ) {
          childDom = this.makeChessDom();
          dom.appendChild(childDom);
          newChess.colorType = 2; // 初始化白子
          newChess.blank = false;
        } else if (
          (i === middle && j === middle - 1) ||
          (i === middle - 1 && j === middle)
        ) {
          childDom = this.makeChessDom();
          dom.appendChild(childDom);
          newChess.colorType = 1; // 初始化黑子
          newChess.blank = false;
        } else {
          utils.addEvent(dom, "click", this.fallChess.bind(this, newChess));
        }
        this.container.style.width = width * dimension + 1 + "px";
        this.container.style.height = width * dimension + 1 + "px";
        this.container.appendChild(dom);
        if (j === lenDimension) {
          valueStr += newChess.value + "\n";
        } else {
          valueStr += newChess.value + "\t";
        }
        if ((i === 0 && j === 0) || (i === 0 && j === lenDimension) || (i === lenDimension && j === lenDimension) || (i === lenDimension && j === 0)) {
          newChess.value = this._maxValue; // 定子赋值最大价值100
          // this._goldCorner.push(newChess);
        }
        // _maxValue = 100; // 定子 金角
        // _secondValue = 45 // 
        // _thirdValue = 10
        // _fourValue = 5
        // _fiveValue = 3
        // _sixValue = 2
        // _sevenValue = 1
        // _eightValue = -5
        // _nineValue = -45

        if (
          (2 <= j && j <= lenDimension - 2 && 0 <= i && i <= middle -3) ||
          (2 <= i && i <= lenDimension - 2 && 0 <= j && j <= middle -3) ||
          (2 <= j && j <= lenDimension - 2 && middle + 2 <= i && i <= lenDimension) ||
          (2 <= i && i <= lenDimension - 2 && middle + 2 <= j && j <= lenDimension)
        )
        { // 拿到所有银边
          newChess.value = this._thirdValue // 外围线的估值 第三高
          if (i === 0 || j === 0 || i === lenDimension || j === lenDimension) {
            if (j === 1 || i === 1 || i === lenDimension - 1 || j === lenDimension - 1) {
              newChess.value = this._eightValue // 金角直线上的第一个点 权重倒数第二
            }
          }
          console.log('newChess dom dom', newChess.dom)
        }
        boardArr[i][j] = newChess;
      }
      // console.log(valueStr);
    }
    this._board = boardArr;
    this.createOther();
    return this;
  }

  makeChessDom() {
    let childDom = document.createElement("div");
    childDom.classList.add("chess");
    if (this.currentColorType === 2) {
      childDom.classList.add("change");
    }

    let blackDom = document.createElement("div");
    blackDom.classList.add("chess-black");
    let whiteDom = document.createElement("div");
    whiteDom.classList.add("chess-white");

    childDom.appendChild(blackDom);
    childDom.appendChild(whiteDom);

    return childDom;
  }

  createOther() {
    let tipDom = document.createElement("div");
    tipDom.classList.add("tips");
    tipDom.classList.add("none");
    this._tipDom = tipDom;
    this.container.appendChild(tipDom);
    let infoDom = document.createElement("div");
    infoDom.classList.add("info");
    infoDom.innerHTML = "黑子数量：2" + "&nbsp;" + "白子数量：2";
    infoDom.style.top = this.container.style.height;
    this._infoDom = infoDom;
    this.container.appendChild(infoDom);
  }

  printValue() {
    const dimension = this.dimension;
    for (let i = 0; i < dimension; i++) {
      let valueStr = "";
      for (let j = 0; j < dimension; j++) {
        let newChess = this._board[i][j]
        if (j === dimension - 1) {
          valueStr += newChess.value + "\n";
        } else {
          valueStr += newChess.value + "\t";
        }
      }
      console.log(valueStr);
    }
  }

  getMaxValue() {
    // 根据估价找到最适合下的棋点
    if (this._dots.length) {
      let maxValueDots; // 存储价值最高的棋点
      if (this._dots.length === 1) {
        return (maxValueDots = this._dots[0]);
      }
      maxValueDots = this._dots[0];
      this._dots.map(function (item) {
        if (item.value > maxValueDots.value) {
          maxValueDots = item;
        }
      });
      return maxValueDots;
    }
  }

  resize(width) {
    for (let i = 0; i < this.dimension; i++) {
      for (let j = 0; j < this.dimension; j++) {
        const dom = this._board[i][j].dom;
        dom.style.width = width + "px";
        dom.style.height = width + "px";
        this.container.style.width = width * this.dimension + 1 + "px";
        this.container.style.height = width * this.dimension + 1 + "px";
      }
    }
  }

  getFall() {
    // 找到可以落子的节点
    const _this = this;
    _this._dots = [];
    for (let i = 0; i < this.dimension; i++) {
      for (let j = 0; j < this.dimension; j++) {
        let item = this._board[i][j];
        item.canFalling = this.canFall(item);
        // console.log("item.canFalling", item.canFalling);
        if (item.colorType === 0) {
          let className = "black-dot";
          if (_this.currentColorType === 2) {
            className = "white-dot";
          }
          if (item.canFalling) {
            item.dom.innerHTML = '<div class="' + className + '"></div>';
            this._dots.push(item);
          } else {
            item.dom.innerHTML = "";
          }
        }
      }
    }
    // this.resetFall();
    return this;
  }

  getCorners() { // 获取所有金角 并根据金角获取最差点
    const _this = this
    const dimension = _this.dimension
    _this._goldCorner = []
    let goldCorner = [];
    for (let i = 0; i < dimension; i++) {
      for (let j = 0; j < dimension; j++) {
        if ((i === 0 && j === 0) || (i === 0 && j === dimension - 1) || (i === dimension - 1 && j === 0) || (i === dimension - 1 && j === dimension - 1)) {
          let curChess = _this._board[i][j]
          if (curChess.colorType === 0) {
            curChess.value = _this._maxValue; // 金角赋值最大价值1000
            goldCorner.push(curChess);
          }
        }
      }
    }
    _this._goldCorner.push(goldCorner)
    _this.getOtherCorners()
    _this.calcCorner()
    _this.printValue()
    // console.log(_this._goldCorner)
  }

  getOtherCorners() {
    const _this = this
    const count = _this.dimension / 2 - 2
    const goldCorners = _this._goldCorner
    const goldCorner = goldCorners[0]
    for (let i = 0; i < goldCorner.length; i++) {
      const direction = _this._cornerDirect2[i]
      let curChess = goldCorner[i]
      let times = 0;
      while (curChess[direction[0]]) {
        ++times
        if (times > count) {
          break
        }
        if (curChess.value === _this._maxValue) {
          curChess[direction[0]].value = -(curChess.value)
        } else {
          curChess[direction[0]].value = 1000 - 50 * (times - 1)
        }
        if (!goldCorners[times]) {
          goldCorners.push([curChess[direction[0]]])
        } else {
          goldCorners[times].push(curChess[direction[0]])
        }
        curChess = curChess[direction[0]]
      }
    }
  }

  calcCorner() {
    const len = this._goldCorner.length
    if (len) {
      for (let i = 0; i < len; i++) {
        const corners = this._goldCorner[i]
        for (let j = 0; j < corners.length; j++) {
          const corner = corners[j]
          this._storeGoldCorner = corner
          this.handleCorner(corner, j)
        }
      }
    }
  }
  handleCorner(corner, index) {
    const _this = this
    // 开始估价
    // const dimension = (this.dimension - 2) / 2;
    let times = 0
    this._cornerDirect1[index].map(function (direct, innerIndex) {
      ++times
      const dimension = (_this.dimension - times * 2) / 2;
      let innerTimes = 1
      while (corner[direct]) {
        ++innerTimes
        if ((innerTimes + 1) % 2 === 0) {
          corner[direct].value = -(corner.value / 2)
        } else {
          corner[direct].value = -(corner.value)
        }
        console.log('corner[direct]', corner[direct])
        if (innerTimes > dimension) {
          innerTimes = 1
          times = 0
          corner = _this._storeGoldCorner
          break;
        }
        corner = corner[direct]
      }
    })
    return this;
  }

  calcBlackWhite() {
    const _this = this;
    _this._blackChess = 0;
    _this._whiteChess = 0;
    for (let i = 0; i < _this.dimension; i++) {
      for (let j = 0; j < _this.dimension; j++) {
        const item = _this._board[i][j];
        if (item.colorType === 1) {
          _this._blackChess++;
        }
        if (item.colorType === 2) {
          _this._whiteChess++;
        }
      }
    }

    _this._infoDom.innerHTML =
      "黑子数量：" +
      _this._blackChess +
      "&nbsp;" +
      "白子数量：" +
      _this._whiteChess;
  }

  removeEvent(dom) {
    utils.removeEvent(dom, "click", this.fallChess);
  }

  initDirect() {
    for (let i = 0; i < this.dimension; i++) {
      for (let j = 0; j < this.dimension; j++) {
        this._storeChess = this._board[i][j];
        // console.log(`开始增加链条${i}-${j}`)
        this.makeDirect(this._board[i][j]);
      }
    }
    return this;
  }

  canFall(chess) {
    const _this = this;
    let canFalling = false; // 默认不可落子
    // console.log("evt", evt);
    let diffs = [];
    _this._direct.map((d) => {
      let diff = [];
      let curChess = chess[d[2]];
      let count = 0;
      while (curChess) {
        if (
          curChess.colorType === 0 ||
          (curChess.colorType === _this.currentColorType && count === 0)
        ) {
          break;
        } else if (count > 0 && curChess.colorType === _this.currentColorType) {
          count++;
          diff.push(curChess);
          break;
        } else {
          count++;
          diff.push(curChess);
        }
        curChess = curChess[d[2]];
      }
      if (diff.length > 0) {
        diffs.push(diff);
      }
    });
    if (diffs.length === 0) {
      return false;
    }
    for (let d = 0; d < diffs.length; d++) {
      const item = diffs[d];
      if (item.length < 1) {
        canFalling = false;
        // console.log('canFalling', canFalling)
        return canFalling;
      }
      if (item[item.length - 1].colorType === _this.currentColorType) {
        canFalling = true;
        _this._diffs = diffs;
        // console.log('canFalling', canFalling)
        return canFalling;
      }
    }
    // console.log('canFalling', canFalling)
    return canFalling;
  }

  win() {
    const _this = this;
    _this.calcBlackWhite();
    _this.getFall();
    if (_this._dots.length === 0) {
      let _tipDom = _this._tipDom;
      _tipDom.classList.remove("none");
      if (_this._blackChess > _this._whiteChess) {
        _tipDom.innerHTML = "黑子胜利！";
      } else if (_this._whiteChess > _this._blackChess) {
        _tipDom.innerHTML = "白子胜利！";
      } else {
        _tipDom.innerHTML = "平局！";
      }
      return true;
    }
    return false;
  }

  getGoldCorners() {
    const _this = this
    for (let i = 0; i < _this.dimension; i++) {
      for (let j = 0; j < _this.dimension; j++) {
        let curChess = _this._board[i][j]
        if (curChess.colorType === 0) {
          _this._goldCornerDirect.map(function (item) {
            let isGold = false // 默认不是金角
            // if (_this.currentColorType === _this.aiColor) { // 如果当前是ai下子 就计算金角
              isGold = item.every(function (d) {
                return curChess[d] === null || (curChess[d] && curChess[d].colorType === _this.aiColor)
                // debugger
                // if (curChess[d] !== null) { // 如果有一个方向上不是ai执子颜色的棋子就不是金角 三个方向上都是ai执子颜色的棋子那就是金角
                //   isGold = false
                // }
              })
            // }
            if (isGold) {
              curChess.value = _this._maxValue // 金角价值最大化         
              console.log('curChess', curChess.dom)
            }
          })
        }
      }
    }
  }

  fallChess(chess, evt) {
    const _this = this;
    // _this.getCorners()
    // _this.getGoldCorners()
    if (_this.canFall(chess)) {
      // 如果可以落子
      let diffs = _this._diffs;
      for (let d = 0; d < diffs.length; d++) {
        const item = diffs[d];
        if (
          item.length >= 1 &&
          item[item.length - 1].colorType === _this.currentColorType
        ) {
          const newItem = item.slice(0, item.length - 1);
          for (let j = 0; j < newItem.length; j++) {
            newItem[j].colorType = 3 - newItem[j].colorType; // 翻子
          }
        }
      }
      //落子
      const html = _this.currentColorType === 1 ? "" : " change";
      chess.dom.innerHTML = `<div class="chess${html}"><div class="chess-black"></div><div class="chess-white"></div></div>`;
      chess.colorType = _this.currentColorType;
      _this.currentColorType = 3 - _this.currentColorType;
      _this.win();
      if (gameConfig.gameType === 2 && evt) {
        // 与本地AI娱乐
        const maxValue = _this.getMaxValue();
        console.log("maxValue", maxValue);
        if (maxValue) {
          _this._timer = setTimeout(function () {
            // 延迟半秒后ai再下子
            clearTimeout(_this._timer);
            _this._timer = null;
            _this.fallChess(maxValue, false);
          }, 500);
        }
      }
      if (gameConfig.gameType === 1 && evt) {
        // 与云端AI娱乐
        utils.ajax({
          url: gameConfig.server + "/putChess",
          type: "post",
          data: {
            param: {
              chess: {
                colorType: chess.colorType,
                x: chess.x,
                y: chess.y,
              },
              gameId: gameConfig.gameId,
            },
            ip: "",
            sid: "",
            timestamp: 0,
          },
          dataType: "json",
          timeout: 1000,
          contentType: "application/json",
          success: function (data) {
            data = JSON.parse(data);
            if (data.opFlag) {
              if (data.serviceResult.data) {
                let computerResponseChess =
                  data.serviceResult.data.computerResponseChess;
                // console.log("computerResponseChess", computerResponseChess);
                gameConfig.computerResponseChess = computerResponseChess;
                const chess =
                  _this._board[computerResponseChess.x][
                  computerResponseChess.y
                  ];

                _this._timer = setTimeout(function () {
                  // 延迟半秒后ai再下子
                  clearTimeout(_this._timer);
                  _this._timer = null;
                  _this.fallChess(chess, false);
                }, 500);
              } else {
                return alert("接口出错!");
              }
            }
          },
          error: function (e) {
            // console.log("error", e);
          },
        });
      }
    } else {
      if (_this.win()) {
        return;
      }
      let _tipDom = _this._tipDom;
      _tipDom.classList.remove("none");
      _tipDom.innerHTML = "不可落子";
      if (_this._timer) {
        clearTimeout(_this._timer);
        _this._timer = null;
      }
      _this._timer = setTimeout(function () {
        _tipDom.classList.add("none");
        clearTimeout(_this._timer);
        _this._timer = null;
      }, 1000);
    }
  }
}
